// CyTargetLinker,
// a Cytoscape plugin to extend biological networks with regulatory interaction
// Copyright 2011-2012 BiGCaT Bioinformatics
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.cytoscape.cytargetlinker.internal.dialog;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.cytoscape.application.CyApplicationManager;
import org.cytoscape.application.swing.CySwingApplication;
import org.cytoscape.cytargetlinker.internal.CTLManager;
import org.cytoscape.cytargetlinker.internal.CTLManager.Direction;
import org.cytoscape.model.CyColumn;
import org.cytoscape.model.CyNetwork;

/**
 * dialog to load the regulatory interaction networks
 * network attribute = attribute containing a biological identifier in teh user network
 * RIN directory = directory that contains one or more RIN files
 */
public class CyTargetLinkerDialog extends JDialog {
	
	private CTLManager manager;
	private CySwingApplication swingApplication;
	private CyApplicationManager applicationManager;
	private Map<String, File> rins;
	
	private Java2sAutoComboBox tfUserAttribute;
	private JTextField tfNetName;
	private JTextField dirField;

	private JComboBox networkComboBox;
	private JComboBox cbDirection;

	/**
	 * Constructor CyTargetLinker dialog
	 * @param manager
	 */
	public CyTargetLinkerDialog(CTLManager manager, CyApplicationManager applicationManager, CySwingApplication swingApplication) {
		super(swingApplication.getJFrame());
		
		this.manager = manager;
		this.swingApplication = swingApplication;
		this.applicationManager = applicationManager;
		
		this.setLayout(new BorderLayout());
		this.add(getMainPanel(), BorderLayout.CENTER);
		this.add(getCommandRow(), BorderLayout.SOUTH);
		locate();
		this.setResizable(false);
		this.pack();
	}
	
	private void setDirection() {
		if(cbDirection.getSelectedItem().equals(Direction.SOURCE)) {
			manager.setDirection(Direction.SOURCE);
		} else if (cbDirection.getSelectedItem().equals(Direction.TARGET)) {
			manager.setDirection(Direction.TARGET);
		} else {
			manager.setDirection(Direction.BOTH);
		}
	}	

	private void locate() {
		int sizeX = 400;
		int sizeY = 400;
		this.setSize(sizeX, sizeY);

		Point cyLocation = swingApplication.getJFrame().getLocation(); 
		int cyHeight = swingApplication.getJFrame().getHeight();
		int cyWidth = swingApplication.getJFrame().getWidth();

		Point middle = new Point(cyLocation.x + (cyWidth / 2), cyLocation.y + (cyHeight / 2));

		int locX = middle.x - (sizeX / 2);
		int locY = middle.y - (sizeY / 2);
		this.setLocation(new Point(locX, locY));
	}

	private JPanel getMainPanel() {
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new GridLayout(3, 1));
		
		mainPanel.add(getUserPanel());
		mainPanel.add(getTargetPanel());
		mainPanel.add(getSettings());
		
		return mainPanel;
	}

	private JPanel getSettings() {
		JPanel settingPanel = new JPanel();
		settingPanel.setBorder(BorderFactory.createTitledBorder("Settings"));
		settingPanel.setLayout(new GridLayout(2,2));
		
		settingPanel.add(new Label("Resulting Network name"));
		tfNetName = new JTextField();
		tfNetName.setText("CTL_" + networkComboBox.getSelectedItem());
		tfNetName.setEditable(true);
		settingPanel.add(tfNetName);
		
		settingPanel.add(new Label("Select direction"));
		Vector<Direction> vec = new Vector<Direction>();
		vec.add(Direction.BOTH);
		vec.add(Direction.SOURCE);
		vec.add(Direction.TARGET);
		cbDirection = new JComboBox(vec);
		cbDirection.setSelectedIndex(0);
		cbDirection = new JComboBox(vec);
		cbDirection.setSelectedIndex(0);
		settingPanel.add(cbDirection);
		
		return settingPanel;
	}

	private JPanel getTargetPanel() {
		JPanel targetPanel = new JPanel();
		targetPanel.setBorder(BorderFactory.createTitledBorder("Directory containg regulatory interaction networks"));
		targetPanel.setLayout(new GridLayout(1,3));
		
		targetPanel.add(new Label("Select RINs"));
		
		// TODO: save network dir state for next session!
		dirField = new JTextField("");
		if(manager.getNetworkDir() != null) {
			dirField.setText(manager.getNetworkDir().getAbsolutePath());
			getRINFiles();
		}
		dirField.setEditable(false);
		targetPanel.add(dirField);
		
		JButton browseButton = new JButton("Browse");
		browseButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = new JFileChooser();
			    chooser.setDialogTitle("Select directory containing RINs");
			    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			    if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
			    	File dir = chooser.getSelectedFile();
			    	manager.setNetworkDir(dir);
			    	dirField.setText(dir.getAbsolutePath());
			    	getRINFiles();
			    }
			}
		});
		
		targetPanel.add(browseButton);
		
		return targetPanel;
	}

	private JPanel getUserPanel() {
		JPanel userPanel = new JPanel();
		userPanel.setBorder(BorderFactory.createTitledBorder("User Network"));
		userPanel.setLayout(new GridLayout(2,2));
		
		userPanel.add(new Label("Select User Network"));
		networkComboBox = new JComboBox(getNetworks());
		networkComboBox.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				tfNetName.setText("CTL_" + ((Network)networkComboBox.getSelectedItem()).getName());
				updateAttributeList(((Network)networkComboBox.getSelectedItem()).getNetwork());				
			}
		});
		userPanel.add(networkComboBox);
		
		userPanel.add(new Label("Select your network attribute"));
		List<String> list = new ArrayList<String>();
		// TODO: test if this works
		for(CyColumn col : (((Network)networkComboBox.getSelectedItem()).getNetwork()).getDefaultNodeTable().getColumns()) {
			list.add(col.getName());
		}
		tfUserAttribute = new Java2sAutoComboBox(list);
		
	
		userPanel.add(tfUserAttribute);
		return userPanel;
	}
	
	private void updateAttributeList(CyNetwork network) {
		List<String> list = new ArrayList<String>();
		list.add("");

		for(CyColumn col : network.getDefaultNodeTable().getColumns()) {
			list.add(col.getName());
		}
		tfUserAttribute.setDataList(list);
		tfUserAttribute.setSelectedIndex(0);
	}
	
	private JComponent getCommandRow() {
		JButton ok = new JButton("OK");
		ok.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				if (!tfUserAttribute.getSelectedItem().equals("")) {
					CyNetwork userNet = ((Network)networkComboBox.getSelectedItem()).getNetwork();

					String selectedAttribute = tfUserAttribute.getSelectedItem().toString();

					manager.setUserNetwork(userNet, selectedAttribute);
	
					// Warning if there is no xgmml files is the directory
					// selected
					if (rins.isEmpty() || rins == null) {
						JOptionPane.showMessageDialog(
								swingApplication.getJFrame(),
								"No xgmml file in this Directory.", "Warning",
								JOptionPane.WARNING_MESSAGE);
					} else {
						if (tfNetName.getText().equals("")) {
							manager.setResultingNetworkName("CTL_"
									+ networkComboBox.getSelectedItem());
						} else {
							manager.setResultingNetworkName(tfNetName.getText());
						}
						setDirection();
						dispose();
						RINSelectionDialog dlg = new RINSelectionDialog(
								manager, rins, applicationManager,
								swingApplication);
						dlg.setVisible(true);
					}
				} else {
					if (tfUserAttribute.getSelectedItem().equals("")) {
						JOptionPane.showMessageDialog(
								swingApplication.getJFrame(),
								"No network attribute.", "Warning",
								JOptionPane.WARNING_MESSAGE);

					}
				}
			}
		});
		getRootPane().setDefaultButton(ok);
		JButton cancel = new JButton("Cancel");
		cancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				dispose();
			}
		});
		List<JComponent> buttons = new ArrayList<JComponent>();
		buttons.add(ok);
		buttons.add(cancel);
		JPanel panel = new JPanel();
		LayoutManager layout = new BoxLayout(panel, BoxLayout.X_AXIS);
		panel.setLayout(layout);
		panel.setBorder(BorderFactory.createEmptyBorder(17, 0, 0, 0));
		panel.add(Box.createHorizontalGlue());
		Iterator<JComponent> buttonsIter = buttons.iterator();
		while (buttonsIter.hasNext()) {
			panel.add(buttonsIter.next());
			if (buttonsIter.hasNext()) {
				panel.add(Box.createHorizontalStrut(5));
			}
		}
		return panel;
	}

	private Vector<Network> getNetworks() {
		Vector<Network> vec = new Vector<Network>();

		for (CyNetwork net : manager.getNetMgr().getNetworkSet()) {
//			List<String> list = net.getDefaultNetworkTable().getColumn("name").getValues(String.class);
//			
//			String name = "";
//			if(!list.isEmpty()) {
//				name = list.get(0);
//			}
			String name = net.getDefaultNetworkTable().getRow
					(net.getSUID()).get("name", String.class);
			Network n = new Network(net, name);
			vec.add(n);
		}
		
		return vec;
	}
	
	private class Network {
		private CyNetwork network;
		private String name;
		
		public Network(CyNetwork network, String name) {
			this.network = network;
			this.name = name;
		}

		public CyNetwork getNetwork() {
			return network;
		}

		public String getName() {
			return name;
		}
		
		@Override
		public String toString() {
			return name;
		}
		
	}

	private void getRINFiles() {
		rins = new HashMap<String, File>();
		File file = new File(dirField.getText());
		if (file != null){
			File[] files = file.listFiles();
			
			for (int i = 0; i < files.length; i++) {
				if (files[i].isFile() && files[i].getName().contains(".xgmml")) {
					//we only take the first ten available network files
					if( rins.size()<=10){
						rins.put(files[i].getAbsolutePath(), files[i]);
					}
				}
			}
		}
	}
}

